<%@ Page Language="C#"%>
<%@ Import Namespace="SubSonic" %>
<%@ Import Namespace="System.Data" %>

<%foreach(DataProvider p in DataService.Providers)
 {
     TableSchema.Table[] tables = DataService.GetTables(p.Name);
     TableSchema.Table[] views = DataService.GetViews(p.Name);

%>
namespace <%=p.GeneratedNamespace%>
{
	#region Tables Struct
	public partial struct Tables
	{
		<%
     foreach (TableSchema.Table t in tables)
     {
         if (CodeService.ShouldGenerate(t.Name, p.Name))
         {
%>
		public static string <%=t.ClassName%> = @"<%=t.Name%>";
        <%
         }
     }
%>
	}
	#endregion

    #region View Struct
    public partial struct Views 
    {
		<%
     foreach (TableSchema.Table v in views)
     {
         if (CodeService.ShouldGenerate(v.Name, p.Name))
         {
%>
		public static string <%=v.ClassName%> = @"<%=v.Name%>";
        <%
         }
     }
%>
    }
    #endregion
    
    #region Query Factories
	public static partial class DB
	{
	    public static Select SelectAllColumnsFrom<T>() where T : RecordBase<T>, new()
	    {
	        return SubSonic.Select.AllColumnsFrom<T>();
	    }
	        
	    public static Select Select()
	    {
	        return new Select(DataService.Providers["<%=p.Name%>"]);
	    }
	    
		public static Select Select(params string[] columns)
		{
	        return new Select(DataService.Providers["<%=p.Name%>"], columns);
	    }
	    
		public static Select Select(params Aggregate[] aggregates)
		{
	        return new Select(DataService.Providers["<%=p.Name%>"], aggregates);
	    }
   
	    public static Update Update<T>() where T : ActiveRecord<T>, new()
	    {
	        return new SubSonic.Update(new T().GetSchema());
	    }     
	    
	    public static Insert Insert()
	    {
	        Insert i=new Insert();
	        i.provider = DataService.Providers["<%=p.Name%>"];
	        return i;
	    }
	    
	    public static Delete Delete()
	    {
	        return new Delete("<%=p.Name%>");
	    }
	    
	    public static InlineQuery Query()
	    {
   	        return new InlineQuery("<%=p.Name%>");
	    }
	    
	    <%if (p.TableBaseClass=="RepositoryRecord"){%>
	    #region Repository Compliance
	    
        public static T Get<T>(object primaryKeyValue) where T : RepositoryRecord<T>, new() 
        {
            T item = new T();
            TableSchema.Table tbl=item.GetSchema();
            string pkColumn = tbl.PrimaryKey.ColumnName;
            IDataReader rdr = SelectAllColumnsFrom<T>().Where(pkColumn)
                .IsEqualTo(primaryKeyValue).ExecuteReader();
            
            if(rdr.Read())
                item.Load(rdr);
            
            return item;
        }

        public static T Get<T>(string columnName, object columnValue) where T : RepositoryRecord<T>, new()
        {
            T item = new T();
            IDataReader rdr = SelectAllColumnsFrom<T>().Where(columnName)
                .IsEqualTo(columnValue).ExecuteReader();

            if (rdr.Read())
                item.Load(rdr);

            return item;
        }
        
        public static void Delete<T>(string columnName, object columnValue) where T : RepositoryRecord<T>, new() 
        {
            T item = new T();
            TableSchema.Table tbl = item.GetSchema();

            if (tbl.GetColumn("Deleted") != null) 
            {
                //create an update command
                new Update(tbl).Set("Deleted").EqualTo(true).Where(columnName).IsEqualTo(columnValue).Execute();

            }
            else if (tbl.GetColumn("IsDeleted") != null) 
            {
                new Update(tbl).Set("IsDeleted").EqualTo(true).Where(columnName).IsEqualTo(columnValue).Execute();
            } 
            else 
            {
                QueryCommand del = ActiveHelper<T>.GetDeleteCommand(columnName, columnValue);
                DataService.ExecuteQuery(del);
            }
        }

        public static void Delete<T>(RepositoryRecord<T> item) where T : RepositoryRecord<T>, new() 
        {
            TableSchema.Table tbl = item.GetSchema();
            string pkColumn = tbl.PrimaryKey.ColumnName;
            object pkValue = item.GetColumnValue(pkColumn);

            Delete<T>(pkColumn, pkValue);
        }
        
        public static void Destroy<T>(RepositoryRecord<T> item) where T : RepositoryRecord<T>, new() 
        {
            TableSchema.Table tbl = item.GetSchema();
            string pkColumn = tbl.PrimaryKey.ColumnName;
            object pkValue = item.GetColumnValue(pkColumn);

            new Delete().From(tbl).Where(pkColumn).IsEqualTo(pkValue).Execute();
        }
        
        public static void Destroy<T>(string columnName, object value) where T : RepositoryRecord<T>, new() 
        {
            T item = new T();
            TableSchema.Table tbl = item.GetSchema();
            new Delete().From(tbl).Where(columnName).IsEqualTo(value).Execute();
        }

        public static int Save<T>(RepositoryRecord<T> item) where T : RepositoryRecord<T>, new() 
        {
            return Save<T>(item, "");
        }
        
        public static int Save<T>(RepositoryRecord<T> item, string userName) where T : RepositoryRecord<T>, new()
        {
            //validation
            int result = 0;
            item.ValidateColumnSettings();
            if (item.HasErrors())
            {
                StringBuilder sb=new StringBuilder();
                List<string> errors = item.GetErrors();
                foreach (string error in errors)
                {
                    sb.Append(error + Environment.NewLine);
                }

                throw new SubSonic.SqlQueryException("There are errors saving this item: "+sb.ToString());
            }
            else
            {
                if (item.IsNew)
                    result = Insert<T>(item,userName);
                else
                    result = Update<T>(item,userName);
            }
            item.DirtyColumns.Clear();
            item.MarkOld();
            item.MarkClean();

	        return result;
        }

        public static int Update<T>(RepositoryRecord<T> item) where T : RepositoryRecord<T>, new() 
        {
	        return Update<T>(item, "");
	    }

        internal static int Update<T>(RepositoryRecord<T> item, string userName) where T: RepositoryRecord<T>, new() 
        {
            if (userName == null) throw new ArgumentNullException("userName");
            int result = 0;
            
            QueryCommand cmd = ActiveHelper<T>.GetUpdateCommand(item, userName);
            result = DataService.ExecuteQuery(cmd);

            return result;
        }

        internal static int Insert<T>(RepositoryRecord<T> item) where T : RepositoryRecord<T>, new() 
        {
            return Insert<T>(item, "");
        }

        static int Insert<T>(RepositoryRecord<T> item, string userName) where T : RepositoryRecord<T>, new() 
        {
            if (userName == null) 
                throw new ArgumentNullException("userName");
            int result = 0;
            QueryCommand cmd = ActiveHelper<T>.GetInsertCommand(item, userName);
            object qResult = DataService.ExecuteScalar(cmd);

            if (qResult != null)
                item.SetColumnValue(item.GetSchema().PrimaryKey.ColumnName, qResult);

            return result;
        }

	    #endregion
        <%}%>
	}
    #endregion
    
}
<%} %>


#region Databases
public partial struct Databases 
{
	<%foreach (DataProvider p in DataService.Providers) { %>
	public static string <%= p.Name %> = @"<%= p.Name%>";
    <%}%>
}
#endregion